#ifndef MOVE_OBJECT_H
#define MOVE_OBJECT_H

#include <QPoint>
#include <QRect>
#include <QString>
#include <QPixmap>
#include <QPainter>
#include <QList>
#include <QBrush>
#include <thread>
#include <complex>
#include <random>
#include <ctime>

#include <windows.h>

#include "config.h"
#include "bomb.h"

namespace Object {      // 该名字空间负责管理移动物体

    using std::complex;
    using std::uniform_int_distribution;
    using std::default_random_engine;

    class Move_object {     // Move_object是一个可移动、可碰撞的物体
    public:
        Move_object(QString pix_path, QPoint pos, int spd, QRect scrn) : pixmap{pix_path}, rect{pos,pixmap.size()}, speed{spd}, screen{scrn} { }
        virtual void draw_this(QPixmap* pix) const;     // 绘制自己
        QRect get_rect() const { return rect; }
        virtual void move_center(QPoint pos) { rect.moveCenter(pos); }
        virtual ~Move_object() { }
    protected:
        void offset_move(int y_up) { rect.moveTop(rect.y()-y_up); }
        bool collision(Move_object other) const { return rect.intersects(other.get_rect()); }
        void move(QPoint pos) { rect.moveTo(pos); }
        int get_speed() const { return speed; }
        bool auto_destroy() const;      // 超出屏幕自动销毁
        QRect get_screen() const { return screen; }
        void set_pixmap(QString pix_path);      // 重置图像
    private:
        QPixmap pixmap;
        QRect rect;
        int speed;
        QRect screen;
    };

    class Bullet : public Move_object {     // Bullet类是一个子弹
    public:
        Bullet(QString b_path, int spd, QRect scrn) : Move_object{b_path,QPoint{0,0},spd,scrn} { }
        bool update_pos();      // 更新位置，返回是否超出屏幕
    };

    class Live_object : public Move_object {        // Live_object类是一个有生命，可以中弹、可以发射子弹的物体
    public:
        Live_object(QString pix_path, QPoint pos, int spd, QRect scrn) : Move_object{pix_path,pos,spd,scrn} { }
        virtual void shoot(QList<Bullet>& bullets) = 0;     // 如果间隔到了，就发射子弹
    protected:
        virtual void init_pos() = 0;        // 初始化位置
        bool destroy_collision(QList<Bullet>& bullets, QList<Bomb::Bomb>& bombs) const;     // 如果与任何一个bullet碰撞，去除该子弹并返回true
        bool interval();        // 发射间隔到了
        void set_interval(int itv);     // 设定发射间隔
    private:
        int shoot_interval;
        int init_interval;
    };

    class Enemy;

    class Player : public Live_object {     // Player类是一辆自机
    public:
        explicit Player(QRect scrn, QString path =player_path, int spd =player_speed) : Live_object{path,QPoint{0,0},spd,scrn}, keyboard{default_state!=State::mouse} { init_pos(); }
        void move_up();     // 向上移动
        void move_down();       // 向下移动
        void move_right();      // 向右移动
        void move_left();       // 向左移动
        void shoot(QList<Bullet>& bullets) override;        // 发射子弹
        void draw_this(QPixmap *pix) const override;        // 绘制自己
        bool collision(QList<Enemy>& enemys, QList<Bullet>& bullets, QList<Bomb::Bomb>& bombs) const;       // 碰撞检测
        bool collision(QRect rect) const;       // 与矩形的碰撞检测
        void set_state(bool key) { keyboard = key; }
        QRect center_point() const;     // 获得判定点判定
        void mouse_move(QPoint pos);        // 跟随鼠标移动
        void move_center(QPoint pos) override;      // 移动中心
    private:
        void init_pos() override;       // 初始化位置
        bool enemy_collision(QList<Enemy>& enemys, QList<Bomb::Bomb>& bombs) const;     // 对敌碰撞检测
        bool keyboard;
    };

    class Enemy : public Live_object {      // Enemy类是一个敌人小兵
    public:
        explicit Enemy(QRect scrn, QString path =player_path, int spd =-enemy_speed) : Live_object{path,QPoint{0,0},spd,scrn} { init_pos(); }
        bool update_pos(QList<Bullet>& bullets, QList<Bomb::Bomb>& bombs);      // 更新位置
        void shoot(QList<Bullet>& bullets) override;        // 发射子弹
    private:
        void init_pos() override;       // 初始化位置
        static int rand_pix_num(complex<int> index =enemy_path_index) { return uniform_int_distribution<>{index.real(),index.imag()}(eng); }
        static default_random_engine eng;
    };

    class Boss : public Live_object {       // Boss类是一个难缠的敌人,与小兵相似度不高所以没有继承Enemy类
    public:
        explicit Boss(QRect scrn, QString path =boss_path, int spd =boss_speed) : Live_object{path,QPoint{0,0},spd,scrn}, seen{false}, health{boss_health} { }
        void to_scene(int c_x);     // 出场
        bool update(QList<Bullet>& bullets, QList<Bullet>& boss_bullets, QList<Bomb::Bomb>& bombs);     // 更新位置并检测碰撞
        void draw_this(QPixmap* pix) const override;        // 绘制自己和血条
        bool beat_player(const Player* player, QList<Bomb::Bomb>& bombs) const;     // 让Boss判断他是否击败了玩家
        void practice_update(QList<Bullet>& boss_bullets);      // 练习模式
    private:
        void init_pos() override;       // 根据中心设定出场初始位置
        void shoot(QList<Bullet>& bullets) override;        // 射击
        int center_x;
        bool seen;
        int health;
        int stay;
        int light;
        void draw_health(QPixmap* pix) const;       // 绘制血条
        QRect light_rect() const;       // 生成光线矩形
        static void light_beep(int sound, int time) { Beep(sound, time); }
    };

}

#endif // MOVE_OBJECT_H
